package SGEngine

import (
	//"fmt"
	"github.com/gl"
)

//Interface/////////////////////////////
type ITransfrom interface {
	GetPosition() (float64, float64, float64)
	GetPositionV() Vec3
	GetScale() (float64, float64, float64)
	GetScaleV() Vec3

	SetPosition(float64, float64, float64)
	SetPositionV(Vec3)
	SetScale(float64, float64, float64)
	SetScaleV(Vec3)

	Size() *Vec3
	SetSizeV(Vec3)
	SetSize(float64, float64, float64)
	Rotate(float64, float64, float64, float64)
	GetMat() *Mat4
	SetMat(*Mat4)

	GetT() *Transfrom

	TransfromNode()
	EndTransfromNode()

	GetR() float64
	GetRdir() *Vec3

	IsSizeScale() bool
	SetIsSizeScale(b bool)

	ToWorldPostion() Vec3
	ToWorldScale() Vec3
}

///////////////////////////////////////
type Transfrom struct {
	Mnode INode
	size  Vec3

	R             float64
	Rdir          Vec3
	Mat           *Mat4
	WorldMat      *Mat4
	TransfromFunc func(INode)

	MisSizeScale bool
}

func (t *Transfrom) ToWorldPostion() Vec3 {
	var RV Vec3
	RV = t.GetPositionV()
	PNode := t.Mnode
	for {
		PNode = PNode.Parent()
		if PNode == nil {
			break
		}
		X, Y, Z := PNode.GetTransfrom().GetPosition()
		RV.X = RV.X + X
		RV.Y = RV.Y + Y
		RV.Z = RV.Z + Z
	}
	return RV
}

func (t *Transfrom) ToWorldScale() Vec3 {
	var RV Vec3
	RV = t.GetScaleV()
	PNode := t.Mnode
	for {
		PNode = PNode.Parent()
		if PNode == nil {
			break
		}
		X, Y, Z := PNode.GetTransfrom().GetScale()
		RV.X = RV.X * X
		RV.Y = RV.Y * Y
		RV.Z = RV.Z * Z
	}
	return RV
}

func (t *Transfrom) IsSizeScale() bool {
	return t.MisSizeScale
}

func (t *Transfrom) SetIsSizeScale(b bool) {
	t.MisSizeScale = b
}

func (t *Transfrom) GetR() float64 {
	return t.R
}

func (t *Transfrom) GetRdir() *Vec3 {
	return &t.Rdir
}

func (t *Transfrom) TransfromNode() {

	gl.MultMatrixd((*[16]float64)(t.Mat))
	//fmt.Println((*[16]float64)(t.Mat))
	gl.Rotated(t.R, t.Rdir.X, t.Rdir.Y, t.Rdir.Z)
	if t.IsSizeScale() {
		gl.Scaled(t.Size().X, t.Size().Y, t.Size().Z)
	}
}

func (t *Transfrom) EndTransfromNode() {
	if t.IsSizeScale() {
		gl.Scaled(1/t.Size().X, 1/t.Size().Y, 1/t.Size().Z)
	}
}

func newBaseTransfrom() *Transfrom {
	return new(Transfrom)
}

func (t *Transfrom) GetT() *Transfrom {

	return t
}

func (t *Transfrom) SetMat(m *Mat4) {
	t.Mat = m
}
func (t *Transfrom) GetMat() *Mat4 {

	return t.Mat
}

func (t *Transfrom) SetSize(x, y, z float64) {
	t.size.X = x
	t.size.Y = y
	t.size.Z = z
}

func (t *Transfrom) SetSizeV(v Vec3) {
	t.size.X = v.X
	t.size.Y = v.Y
	t.size.Z = v.Z
}

func (t *Transfrom) Size() *Vec3 {

	return &t.size
}

func (t *Transfrom) GetPosition() (_x, _y, _z float64) {
	return t.Mat[12], t.Mat[13], t.Mat[14]
}

func (t *Transfrom) GetPositionV() Vec3 {
	return Vec3{t.Mat[12], t.Mat[13], t.Mat[14]}
}

func (t *Transfrom) GetScale() (_x, _y, _z float64) {
	return t.Mat[0], t.Mat[5], t.Mat[10]
}
func (t *Transfrom) GetScaleV() Vec3 {
	return Vec3{t.Mat[0], t.Mat[5], t.Mat[10]}
}
func (t *Transfrom) SetPosition(_x, _y, _z float64) {
	t.Mat[12] = _x
	t.Mat[13] = _y
	t.Mat[14] = _z
	//t.pos.X = _x
	//t.pos.Y = _y
	//t.pos.Z = _z
}

func (t *Transfrom) SetScale(_x, _y, _z float64) {
	t.Mat[0] = _x
	t.Mat[5] = _y
	t.Mat[10] = _z
}

func (t *Transfrom) SetScaleV(_v Vec3) {
	t.Mat[0] = _v.X
	t.Mat[5] = _v.Y
	t.Mat[10] = _v.Z
}
func (t *Transfrom) SetPositionV(_v Vec3) {
	t.Mat[12] = _v.X
	t.Mat[13] = _v.Y
	t.Mat[14] = _v.Z
}

func (t *Transfrom) Rotate(r float64, X, Y, Z float64) {
	t.Rdir.X = X
	t.Rdir.Y = Y
	t.Rdir.Z = Z
	t.R = r
}
